import produce from 'immer';
import { useState, useCallback } from 'react';

/**
 * 类似 useState，但是 setState 换成 setDraft，可以直接对 draft 进行变更操作，相当于升级版的 setState
 * @param initState 效果同 useState，可是写值，表达式，或者返回值的函数
 * usage: [state, setDraft, setState] = useDraft(initialState)
 * 返回第一项 state 为状态数据。通常使用 useDraft 的数据，都不是简单数据，而是有结构并且有一定深度的数据，否则直接 useState 就可以了
 * 返回第二项 setDraft 为通过 immer draft 来设置。
 * 返回第三项 setState 同内部的 useState 返回的 setState，为了能够用传统方式设置，或者是全新设置状态而非draft修改
 *   通常 setDraft(cb) cb 也可以不修改 draft 直接返回新状态，相当于 setState 的作用，因此返回第三项经常不用
 * 生态位说明
 * 基于 useDraft 比直接 useState 更方便，因为可以直接方式直观的修改 state，而不是产生新版本 state
 * 基于 useDraft 可以在包装指定的多个 methods 已特定的方式修改 state，作为自定义 hook 供组件使用
 * 比 useReducer 更为方便，不用 dispatch(action) 而是直接 action(params)，类型提示和类型保护支持到位
 */
function useDraft(initState: any) {
  const [state, setState] = useState(initState);
  const setDraft = useCallback((cb) => setState(produce(cb)), []);
  return [state, setDraft, setState];
}

export default useDraft;
export { useDraft };
